#include <iostream>

using std::cout;
using std::endl;

class Point
{
public:
    Point(int ix = 0, int iy = 0)
    : _ix(ix)
    , _iy(iy)
    {
        cout << "Point(int = 0, int = 0)" << endl;
    }

    //Q1:拷贝构造函数参数中的引用符号能不能去掉？
    //A1:引用符号不能去掉，因为如果去掉引用符号，那么在进行
    //形参与实参结合的时候，会调用拷贝构造函数，而拷贝构造函数
    //现在没有引用符号，那么就是用一个已经存在的对象初始化
    //一个刚刚创建的对象，也就是满足拷贝构造函数的调用时机1，
    //会继续无限的调用拷贝构造函数，而函数的参数是会入栈的，
    //而栈是有大小的，这样就将栈压垮，导致栈溢出
    //
    //Q2：拷贝构造函数参数中的const可以去掉吗？
    //A2:不能去掉，当执行拷贝构造函数的时候，如果传递进来的
    //参数是右值的时候，会出现非const左值引用不能绑定到右值
    //就会出现错误。（注意：没有const的时候，传递的参数是
    //左值是没有问题）
    //
    //编译器会自动生成拷贝构造函数
    Point(const Point &rhs)
    : _ix(rhs._ix)
    , _iy(rhs._iy)
    {
        cout << "Point(const Point &)" << endl;
    }

    void print()
    {
        cout << "(" << _ix 
             << ", " << _iy
             << ")" << endl;
    }

    ~Point()
    {
        cout << "~Point()" << endl;
    }

private:
    int _ix;
    int _iy;
};

void test()
{
    Point pt;
    cout << "pt = ";
    pt.print();

    cout << endl;
    Point pt2(3, 4);
    cout << "pt2 = ";
    pt2.print();
}


void test2()
{
    int a = 10;
    int b = a;
    cout << "a = " << a << endl
         << "b = " << b << endl;

    cout << endl;
    Point pt1(1, 2);
    cout << "pt1 = ";
    pt1.print();

    cout << endl;
    //拷贝构造函数的调用时机1：当用一个已经存在的对象去初始化
    //一个刚刚创建的对象，会调用拷贝构造函数
    Point pt2 = pt1;
    cout << "pt2 = ";
    pt2.print();
}

//void func(int a)//func(b) int a = b

//func(pt1)
//拷贝构造函数的调用时机2：当函数的参数是类类型的时候，在进行
//形参与实参结合的时候，会调用拷贝构造函数
//Point(const Point rhs)
//const Point rhs = pt1
//const Point rhs = pt1
//const Point rhs = pt1
void func(Point pt)//Point pt = pt1
{
    cout << "pt = ";
    pt.print();
}

void test3()
{
    Point pt1(1, 2);
    cout << "pt1 = ";
    pt1.print();

    cout << endl;
    func(pt1);

}

int func33()
{
    int number = 10;
    return number;//将number的值拷贝出去
}

//拷贝构造函数的调用时机3：当函数的返回类型是类类型的时候，
//在执行return语句的时候，会执行拷贝构造函数
//-fno-elide-constructors
Point func3()
{
    Point pt3(3, 4);
    cout << "pt3 = ";
    pt3.print();

    return pt3;//将pt3值拷贝出去
}

void test4()
{
    int number = 10;
    int &ref = number;
    &ref;
    &number;//ok,左值
    const int &ref2 = 10;
    const int &ref3 = number;
    &ref2;
    /* &10;//error */

    //func3(),临时对象/匿名对象,生命周期比较短,该对象的创建与
    //销毁都在本行，临时对象只是起了桥梁作用
    //Point(Point &rhs)
    /* &func3();//error,右值，不能取地址 */
    /* const Point &rhs = func3();//ok */
    Point pt4 = func3(); 
    cout << "pt4 = ";
    pt4.print();
}


int main(int argc, char **argv)
{
    test4();
    return 0;
}

